﻿using System;
using System.Collections.Generic;
using AOT.Game.ID;
using AOT.Game.Timer;
using UnityEngine;
using UnityEngine.Pool;
using Wxy.Res;

namespace AOT.Sound
{
    public class SoundPlayer : MonoBehaviour
    {
        private IdPool _idPool;
        private ResMgr _resMgr;
        private ScriptTimer _timer;
        private Dictionary<long, (long, AudioSource)> _soundSourceDic;
        private ObjectPool<AudioSource> _audioSourcePool;

        public void Init(ResMgr resMgr, ScriptTimer timer)
        {
            _resMgr = resMgr;
            _timer = timer;
            _idPool = new IdPool(2, 100);
            _soundSourceDic = new();
            _audioSourcePool = new ObjectPool<AudioSource>(createFunc: () =>
            {
                return gameObject.AddComponent<AudioSource>();
            });
        }

        public long PlaySoundByPath(string audioPath)
        {
            AudioClip audioClip = _resMgr.LoadAsset<AudioClip>(audioPath);
            return PlaySoundByAudioClip(audioClip);
        }
        
        public float GetSoundLength(long soundId)
        {
            if (_soundSourceDic.ContainsKey(soundId))
            {
                var audioSource = _soundSourceDic[soundId].Item2;
                return audioSource.clip.length;
            }
            return 0;
        }

        public long PlaySoundByAudioClip(AudioClip audioClip)
        {
            var audioSource = _audioSourcePool.Get();
            audioSource.clip = audioClip;
            audioSource.loop = false;
            audioSource.Play();
            long soundId = _idPool.GetId();
            long id = _timer.DoThingAfterTime(audioClip.length, () =>
            {
                StopSoundById(soundId);
            });
            _soundSourceDic.Add(soundId, (id, audioSource));
            return soundId;
        }

        public bool StopSoundById(long soundId)
        {
            if (_soundSourceDic.ContainsKey(soundId))
            {
                var timerId = _soundSourceDic[soundId].Item1;
                var audioSource = _soundSourceDic[soundId].Item2;
                _timer.TryStopTimerById(timerId);
                audioSource.Stop();
                audioSource.clip = null;
                _idPool.ReturnId(soundId);
                _audioSourcePool.Release(audioSource);
                _soundSourceDic.Remove(soundId);
                return true;
            }
            return false;
        }

        public void PlayBackgroundMusic(string audioPath)
        {
            AudioClip audioClip = _resMgr.LoadAsset<AudioClip>(audioPath);
            var audioSource = _audioSourcePool.Get();
            audioSource.clip = audioClip;
            audioSource.loop = true;
            audioSource.Play();
        }

        public void StopAllSound()
        {
            foreach (var id in _soundSourceDic.Keys)
            {
                StopSoundById(id);
            }
            _soundSourceDic.Clear();
        }

    }
}